#include "../inc/gini.h"

static void   gini_strNon(char * str);
static void*  gini_malloc(int len);

GIni * gini_New(char *pathname){    
    if(pathname == NULL){
        return NULL;
    }else{
        FILE *fp_ini=NULL;
        fp_ini = fopen(pathname,"rw");
        if(fp_ini == NULL){
            return NULL;
        }else{
            GIni * gini= (GIni *)gini_malloc(sizeof(GIni));
            gini->filename = strdup(pathname);
            gini_parse(fp_ini, gini);
            fclose(fp_ini);


            while(1){
                GList *tplist=gini->trunk;
                while(tplist != NULL){
                    GSection *tpSection= (GSection *)(tplist->data);
                    gini_Log("[%s]",tpSection->name);
                    GList *leaflist = tpSection->leaf; 
                    while(leaflist != NULL){
                        GItem * item = (GItem *)leaflist->data;
                        gini_Log(" -%s=%s",item->key,item->value);
                        leaflist = leaflist->next;
                    }
                    tplist = tplist->next;
                }
                break;
            }


            return gini;
        }
    }
}
void gini_parse(FILE *fp_ini,GIni *tree){
    char lineData[GINI_LEN_1024];
    GList *sectionList=NULL;
    GList *leafList=NULL;
    GSection *cu_Section=NULL;
    while(feof(fp_ini)==0){
        memset(lineData,0,sizeof(char)*GINI_LEN_1024);
        fgets(lineData,GINI_LEN_1024,fp_ini);
        gini_strNon(lineData);
        if(strlen(lineData)>2){/*str is [x] or str is x=y*/
            if(lineData[0] == '['){
                char *pos = strstr(lineData,"]");
                int len=pos-&lineData[1];
                char *tn=(char *)malloc(sizeof(char)*(len+1));
                memset(tn,0,sizeof(char)*(len+1));
                strncpy(tn,&lineData[1],len);

                GSection *tmp_Section = gini_malloc(sizeof(GSection));
                tmp_Section->leaf=NULL;
                tmp_Section->name=strdup(tn);
                free(tn);

                GList    *tmp_Glist   = gini_malloc(sizeof(GList));
                tmp_Glist->data = (void *)tmp_Section;
                if(cu_Section==NULL){
                    tree->trunk = tmp_Glist;
                    tree->trunk->next=NULL;
                    tree->trunk->prev=NULL;
                    sectionList = tree->trunk;
                }else{
                    sectionList->next = tmp_Glist;
                    tmp_Glist->prev = sectionList;
                    tmp_Glist->next=NULL;
                    sectionList=tmp_Glist;
                }
                cu_Section = tmp_Section;
            }else{
                char *v=strstr(lineData,"=");
                char *k=(char *)malloc(sizeof(char)*((v-lineData)+1));
                memset(k,0,(v-lineData)+1);
                strncpy(k,lineData,v-lineData);

                GItem *tp_Item = gini_malloc(sizeof(GItem));
                tp_Item->key=strdup(k);
                tp_Item->value=strdup(++v);
                free(k);

                GList * tp_list = gini_malloc(sizeof(GList));
                tp_list->data = (void *)tp_Item;
                if(cu_Section->leaf==NULL){
                    cu_Section->leaf=tp_list;
                    cu_Section->leaf->next=NULL;
                    cu_Section->leaf->prev=NULL;
                    leafList = cu_Section->leaf;            
                }else{
                    leafList->next = tp_list;
                    tp_list->prev = leafList;
                    tp_list->next=NULL;
                    leafList = tp_list;
                }
            }    
        }
    }
}



static void gini_strNon(char * str){
     int len=strlen(str);
        while(str[len-1]=='\n'){
            str[len-1]='\0';
            len = strlen(str);
    }    
}

static void *  gini_malloc(int len){
    void * tmp =NULL;
    tmp = (void *)malloc(sizeof(char) * len);
    memset(tmp,0,sizeof(char)*len);
    return tmp;
}


char * gini_getString(GIni * tree,char * section,char * key){
    static char vstring[GINI_LEN_256];
    memset(vstring,0,GINI_LEN_256);
    GList *tplist=tree->trunk;
    while(tplist != NULL){
        GSection *tpSection= (GSection *)(tplist->data);
        if(!strcmp(tpSection->name,section)){
            GList *leaflist = tpSection->leaf; 
            while(leaflist != NULL){
                GItem * item = (GItem *)leaflist->data;
                if(!strcmp(item->key,key)){
                    strncpy(vstring,item->value,strlen(item->value));
                }
                leaflist = leaflist->next;
            }
        }
        tplist = tplist->next;
    }
    return vstring;
}

int gini_getInt(GIni * tree,char * section,char * key,int default_value){
    char *result=NULL;
    result = gini_getString(tree,section,key);
    if(result){
        return atoi(result);
    }else{
        return default_value;
    }
}

float gini_getFloat(GIni * tree,char * section,char * key,float default_value){
    char *result=NULL;
    result = gini_getString(tree,section,key);
    if(result){
        return atof(result);
    }else{
        return default_value;
    }
}


void gini_setString(GIni * tree,char * section,char * key,char * value){
    
    GList *tplist=tree->trunk;
    GSection *cuSection=NULL;
    GSection * tmpSection=NULL;
    int found_section = 0;
    while(tplist != NULL){
        tmpSection = (GSection *)(tplist->data);
        if(!strcmp(tmpSection->name,section)){
            found_section=1;
            cuSection = tmpSection;
        }
        if(tplist->next != NULL ){
            tplist = tplist->next;
        }else{
            break;
        }
    }
    GSection* x = (GSection*)tplist->data;
    gini_Log("x->name:%s",x->name);
    gini_Log("found_section:%d",found_section);
    if(found_section == 0){

        cuSection= (GSection *)gini_malloc(sizeof(GSection));
        memset(cuSection,0,sizeof(cuSection));
        cuSection->name=strdup(section);
        cuSection->leaf=NULL;
        GList    *new_Glist   = (GList *)gini_malloc(sizeof(GList));
        memset(new_Glist,0,sizeof(GList));
        new_Glist->data =( void *)cuSection;

        tplist->next=new_Glist;
        new_Glist->prev = tplist;
        new_Glist->next=NULL;
    }
    gini_Log("cuSection->name:%s",cuSection->name);
    gini_Log("cuSection->name:%s",cuSection->name);

    GItem *new_Item  = (GItem *)gini_malloc(sizeof(GItem));  
    memset(new_Item,0,sizeof(GItem));
    new_Item->key=strdup(key);
    new_Item->value=strdup(value);   
    gini_Log("add new leaf:<%s:%s>",new_Item->key,new_Item->value);


    GList  *new_Leaf   = (GList *)gini_malloc(sizeof(GList));
    memset(new_Leaf,0,sizeof(GList));
    new_Leaf->data = (void *)new_Item;


    GList *leafList=cuSection->leaf;
    while(leafList != NULL){
        if(leafList->next)
            leafList = leafList->next;
        else
            break;    
    }
    if(leafList){
        leafList->next = new_Leaf;
        new_Leaf->prev = leafList;
        new_Leaf->next=NULL;
    }else{
        leafList=new_Leaf;
        leafList->next=NULL;
        leafList->prev=NULL;
    }
}